Skip to content

own: a const declared from a merge of owning locals borrows them; a value moved into a field of an element read borrows that field (TSLANG 58, 59) - #851

Merged
ASDAlexander77 merged 2 commits into
mainfrom
fix-own-items-58
Nov 14, 2026
Merged

ASDAlexander77 merged 2 commits into
mainfrom
fix-own-items-58

Conversation

@ASDAlexander77

Copy link
Copy Markdown
Owner

TSLANG_ISSUES 58 and 59, found by compiling powder_sandbox's -mm=own build (native_ts_graphics as its submodule) with the compiler from main. Write-ups are in TSLANG_ISSUES.md.

58: a const declared from a merge of owning locals borrows them

const selected = x2py2gez2pw2 ? (x2gey2 ? tensor0 : tensor1) : (z2gew2 ? tensor2 : tensor3) (ntg core/directx_math.ts) was refused: "merged from several branches; -mm=own cannot prove which one owns it yet". So was a plain const s = c ? t0 : t1.

  • Why: each local keeps its value and is released at the end of its scope, so neither value can move into the merge.
  • The fix: a let's retain of a merge whose ways in are each a read of an owning local, or null or undefined (slotLoadsOfMerge), is made a receiver of each of those locals. decideSlot then takes the borrow path for them, so rc's retain and release for the const go, and each local's releases and assignments end the borrow.
  • Still refused: one of the locals assigned or moved while the const is still used; the const stored, returned or assigned.
  • A loop bug, fixed too: takerLoops took a merge's own declaration (its block's first op) as reached again around a loop before the merge is remade. That refused such a merge in a loop's body, and TSLANG 54's const p = c ? mk() : null in a loop as well.
  • Result: directx_math.ts compiles under own. With its facts object built, so does core/simple_camera.ts, which had been refused only for calling into a module with no facts.

59: a value moved into a field of an element or field read, then used, borrows that field

const queuedFrame = this.queuedFrames[i]; ... queuedFrame.aabbAttributeBuffer = buffer; const view = buffer ? buffer.createStructuredView(0) : null; (ntg examples/nri/procedural_geometry_nri.ts) was refused: "used here after its value was moved".

  • Why: TSLANG 50 and 52 read the field back right after the move only through an object read out of a local or parameter nothing assigns. A const given an element is no local by then; it is the element read itself.
  • The fix: right after the store or push nothing runs, so an object read out of an element or a field is the same object there (objectReadableRightAfter). The checks then follow the borrow through that chain.
  • Still refused: the element replaced or popped, the field reset, or the holder's field replaced before a use.
  • Not loops: under 58 I first took this gap to be about loops; it is the element-read object.
  • One site of this shape is left: procedural_geometry_nri.ts:425, which reduced copies of it do not reproduce.

Effect on the sweep (276 sources, every facts object built)

  • Sources failing: 141 → 126.
  • ntg core/ modules that don't compile under own: 6 → 4. Left: donut_first_person_camera, nri_donut_textures, ray_tracing_extended_scene (needs @keeps/Shared<T> in ntg), rtxpt_game.
  • "used here after its value was moved" sites: 49 → 37.
  • One unexplained crash: in one sweep run tslang.exe crashed (0xC0000005) on core/ray_tracing_extended_scene.ts. It did not reproduce in about 45 more runs: alone, six at a time, and a full sweep rerun. Each of those gave its usual 5 errors.

Tests

  • New tests: 00tslang_issue_58.ts and 00tslang_issue_59.ts, under every model, JIT and compiled.
  • New own error tests: own_err_merged_locals_overwritten, own_err_merged_locals_moved and own_err_element_field_moved_replaced.
  • ctest (Windows Release): 7257/7257.
  • DefaultLib main rebuilt with this compiler, release and debug, all four models. tests.ps1 for each model is running; results to follow in a comment.

🤖 Generated with Claude Code

ASDAlexander77 and others added 2 commits November 14, 2026 15:07
…erge made in a loop's body (TSLANG 58)

`const selected = c ? tensor0 : tensor1` (native_ts_graphics core/directx_math.ts) was refused as merged
from several branches. Each local keeps its value, so the const borrows each of them (slotLoadsOfMerge,
decideSlot). takerLoops took a merge's own declaration as reached again around a loop before the merge
is remade, which refused it in a loop's body, and TSLANG 54's fresh merge there too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d, borrows that field (TSLANG 59)

`const frame = this.frames[i]; frame.buf = buf; if (buf) ...` (native_ts_graphics
examples/nri/procedural_geometry_nri.ts) was a use after a move: TSLANG 50/52 read the field back right
after the move only through an object read out of a local or parameter. Right after the store nothing
runs, so an object read out of an element or a field is the same object (objectReadableRightAfter).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ASDAlexander77

Copy link
Copy Markdown
Owner Author

DefaultLib tests.ps1 with this branch's compiler (DefaultLib main at 0fac086 rebuilt, release and debug, all four models). No failures.

model release compile release jit debug compile debug jit
own 217/223, 6 skipped 217/223, 6 skipped 217/223, 6 skipped 217/223, 6 skipped
rc 219/223, 4 skipped 219/223, 4 skipped 219/223, 4 skipped 219/223, 4 skipped
gc 222/223, 1 skipped 222/223, 1 skipped 222/223, 1 skipped 222/223, 1 skipped
none 219/223, 4 skipped 219/223, 4 skipped 219/223, 4 skipped 219/223, 4 skipped

Own skips one more than for #850: array_flatMap_shared.ts, new in DefaultLib #99 and marked not-own there. The other skips are the usual by-design ones.

@ASDAlexander77
ASDAlexander77 merged commit ce60a4c into main Nov 14, 2026
8 checks passed
@ASDAlexander77
ASDAlexander77 deleted the fix-own-items-58 branch November 14, 2026 16:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant